﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management.Automation;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.PowerShell;

namespace Mystery.SharePoint.PowerShell
{
    [SPCmdlet(RequireUserFarmAdmin = true)]
    [Cmdlet("Upgrade", "SPMFeatures")]
    class UpgradeFeaturesCmdlet : SPCmdlet
    {
        [Parameter(Mandatory = true, ValueFromPipeline = true)]
        public SPWebApplicationPipeBind WebApplication { get; set; }

        [Parameter(Mandatory = false)]
        public SwitchParameter Force { get; set; }

        protected override void InternalBeginProcessing()
        {
            SPWebApplication app = this.WebApplication.Read();

            base.Host.UI.WriteLine("Upgrading web application scoped features");
            Upgrade(app.QueryFeatures(SPFeatureScope.WebApplication, true));
            base.Host.UI.WriteLine("Upgrading site collection scoped features");
            Upgrade(app.QueryFeatures(SPFeatureScope.Site, true));
            base.Host.UI.WriteLine("Upgrading web scoped features");
            Upgrade(app.QueryFeatures(SPFeatureScope.Web, true));
        }

        private void Upgrade(SPFeatureQueryResultCollection features)
        {
            try
            {
                foreach (var item in features)
                {
                    string url = "";

                    switch (item.Definition.Scope)
                    {
                        case SPFeatureScope.Site:
                            url = ((SPSite)item.Parent).Url;
                            break;
                        case SPFeatureScope.Web:
                            url = ((SPWeb)item.Parent).Url;
                            break;
                        case SPFeatureScope.WebApplication:
                            url = ((SPWebApplication)item.Parent).GetResponseUri(SPUrlZone.Default).ToString();
                            break;
                        default:
                            break;
                    }
                    base.Host.UI.WriteLine(string.Format("Upgrading {0} at {1}", item.Definition.DisplayName, url));
                    item.Upgrade(this.Force.ToBool());
                }
            }
            catch (System.IO.FileNotFoundException ex)
            {
                base.WriteWarning("The Query to retrieve features that needs upgrading also includes those located in the recycle bin. Empty the recycle bin before running the upgrade.");
                base.WriteError(ex, ErrorCategory.InvalidOperation, this);
                throw;
            }
        }
    }
}
